package com.xiaolong.redis.aspectj;


import com.alibaba.fastjson2.JSON;
import com.xiaolong.common.exception.BusinessException;
import com.xiaolong.redis.annotation.Cache;
import com.xiaolong.redis.factory.CacheHandlerFactory;
import com.xiaolong.redis.util.CacheUtil;
import com.xiaolong.redis.util.PointUtil;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


@Aspect
public class CacheAspect {

    private static final Logger logger = LoggerFactory.getLogger(LockAspect.class);

    private RedissonClient redissonClient;

    public CacheAspect(RedissonClient redissonClient) {
        this.redissonClient = redissonClient;
    }

    @Pointcut("@annotation(com.xiaolong.redis.annotation.Cache)")
    public void lockPointCut() {
    }

    @Around("lockPointCut()")
    public Object around(ProceedingJoinPoint point) throws Throwable {
        Cache cache = PointUtil.getInstance(point, Cache.class);
        String key = cache.key();
        if (CacheUtil.contains(key)) {
            return CacheUtil.strValue(key);
        }
        Object result;
        RLock lock = redissonClient.getLock("LOCK_"+key);
        try {
            lock.lock();
            if (CacheUtil.contains(key)) {
                return CacheUtil.strValue(key);
            }
            result = CacheHandlerFactory.routingCacheHandler(cache.policies()).saveCache(point, cache);
            logger.info("cache refresh success.{}", JSON.toJSONString(result));
        } finally {
            lock.unlock();
        }
        return result;
    }

}
